<template>
    <div :class="classes" v-clickoutside="handleClose">
        <input type="hidden" v-if="name && onlyOne" :name="name" v-model="currentValue">
        <input type="hidden" v-if="name && !onlyOne" v-for="(name,index) in names" :name="name" v-model="currentValue[index]">
        <div :class="[prefixCls + '-rel']" @click="toggleOpen">
            <slot>
                <i-input
                        :readonly="true"
                        :clearable="clearabled"
                        :disabled="disabled"
                        :editable="!disabled"
                        v-model="displayRender"
                        :size="size"
                        :icon="iconType"
                        :placeholder="placeholder"
                        @on-clear="clearSelect"></i-input>
            </slot>
        </div>
        <transition name="slide-up">
            <Drop v-show="visible">
                <div>
                    <Caspanel
                            ref="caspanel"
                            :prefix-cls="prefixCls"
                            :data="data"
                            :disabled="disabled"
                            :change-on-select="changeOnSelect"
                            :trigger="trigger"></Caspanel>
                </div>
            </Drop>
        </transition>
    </div>
</template>
<script>
    import iInput from '../input/input.vue';
    import Drop from '../select/dropdown.vue';
    import Icon from '../icon/icon.vue';
    import Caspanel from './caspanel.vue';
    import clickoutside from '../../directives/clickoutside';
    import {oneOf} from '../../utils/assist';
    import Emitter from '../../mixins/emitter';
    import {emit} from './emit';

    const prefixCls = 'ivu-cascader';

    export default {
        name: 'Cascader',
        mixins: [Emitter],
        components: {iInput, Drop, Icon, Caspanel},
        directives: {clickoutside},
        props: {
            name: [String, Array],
            data: {
                type: Array,
                default () {
                    return [];
                }
            },
            value: {
                type: [Array, String],
                default () {
                    return [];
                }
            },
            disabled: {
                type: Boolean,
                default: false
            },
            clearable: {
                type: Boolean,
                default: true
            },
            readonly: {
                type: Boolean,
                default: false
            },
            placeholder: {
                type: String,
                default: '请选择'
            },
            size: {
                validator (value) {
                    return oneOf(value, ['small', 'large']);
                }
            },
            trigger: {
                validator (value) {
                    return oneOf(value, ['click', 'hover']);
                },
                default: 'click'
            },
            changeOnSelect: {
                type: Boolean,
                default: false
            },
            renderFormat: {
                type: Function,
                default (label) {
                    return label.join(' / ');
                }
            }
        },
        data () {
            return {
                prefixCls: prefixCls,
                visible: false,
                selected: [],
                tmpSelected: [],
                updatingValue: false,    // to fix set value in changeOnSelect type
                currentValue: this.value,
                icon: "arrow-down-b",
                names: []
            };
        },
        computed: {
            classes () {
                return [
                    `${prefixCls}`,
                    {
                        [`${prefixCls}-visible`]: this.visible,
                        [`${prefixCls}-disabled`]: this.disabled
                    }
                ];
            },
            clearabled(){
                if (this.disabled || this.readonly)return false;
                return this.clearable;
            },
            iconType(){
                if (this.readonly || !this.icon)return "";
                return this.icon;
            },
            onlyOne(){
                if (this.names.length == 1)return true;
                return false;
            },
            displayRender () {
                let label = [];
                for (let i = 0; i < this.selected.length; i++) {
                    label.push(this.selected[i].label);
                }

                return this.renderFormat(label, this.selected);
            }
        },
        methods: {
            clearSelect () {
                if (this.disabled || this.readonly) return false;
                const oldVal = JSON.stringify(this.currentValue);
                this.currentValue = this.selected = this.tmpSelected = [];
                this.handleClose();
                this.emitValue(this.currentValue, oldVal);
                this.broadcast('Caspanel', 'on-clear');
            },
            handleClose () {
                this.icon = "arrow-down-b";
                this.visible = false;
            },
            toggleOpen () {
                if (this.disabled || this.readonly) return false;
                if (this.visible) {
                    this.handleClose();
                } else {
                    this.onFocus();
                }
            },
            onFocus () {
                this.icon = "arrow-up-b";
                this.visible = true;
            },
            updateResult (result) {
                this.tmpSelected = result;
            },
            updateSelected (init = false) {
                if (!this.changeOnSelect || init) {
                    this.broadcast('Caspanel', 'on-find-selected', {
                        value: this.currentValue
                    });
                }
            },
            emitValue (val, oldVal) {
                if (JSON.stringify(val) !== oldVal) {
                    this.$emit('on-change', this.currentValue, JSON.parse(JSON.stringify(this.selected)));
                    this.$nextTick(() => {
                        this.dispatch('FormItem', 'on-form-change', {
                            value: this.currentValue,
                            selected: JSON.parse(JSON.stringify(this.selected))
                        });
                    });
                }
            }
        },
        mounted () {
            if (this.name) {
                const type = typeof this.name;
                if (type === 'string') {//值为字符串，则解析为数组
                    this.names = this.name.split(",");
                } else if (Array.isArray(this.name)) {
                    this.names = this.name;
                }
            }

            if (this.value) {
                const type = typeof this.value;
                if (type === 'string') {//值为字符串，则解析为数组
                    this.currentValue = this.value.split(",");
                }
            }

            this.updateSelected(true);
            this.$on('on-result-change', (params) => {
                // lastValue: is click the final val
                // fromInit: is this emit from update value
                const lastValue = params.lastValue;
                const changeOnSelect = params.changeOnSelect;
                const fromInit = params.fromInit;

                if (lastValue || changeOnSelect) {
                    const oldVal = JSON.stringify(this.currentValue);
                    this.selected = this.tmpSelected;

                    let newVal = [];
                    this.selected.forEach((item) => {
                        newVal.push(item.value);
                    });

                    if (!fromInit) {
                        this.updatingValue = true;
                        this.currentValue = newVal;
                        this.emitValue(this.currentValue, oldVal);
                    }
                }
                if (lastValue && !fromInit) {
                    this.handleClose();
                }
            });
            emit.$on("on-click-item", (item) => {
                this.$emit("on-click", item);
            });
        },
        watch: {
            visible (val) {
                if (val) {
                    if (this.currentValue.length) {
                        this.updateSelected();
                    }
                }
                this.$emit('on-visible-change', val);
            },
            value (val) {
                this.currentValue = val;
                if (!val.length) this.selected = [];
            },
            currentValue () {
                this.$emit('input', this.currentValue);
                if (this.updatingValue) {
                    this.updatingValue = false;
                    return;
                }
                this.updateSelected(true);
            },
            data () {
                this.$nextTick(() => this.updateSelected());
            }
        }
    };
</script>
